/*
 * kdogs - Kick dogs, a lightweight watchdog kicker
 *
 * Copyright (C) 2007 Instituto Nokia de Tecnologia
 *
 * Author: Osvaldo Santana Neto <osvaldo.neto@openbossa.org>
 *         Abner Silva <abner.silva@openbossa.org>
 *
 *  This program is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License as published by the
 *  Free Software Foundation version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>

#include "kdogsd.h"
#include "kdogs_sysfs.h"

static int
readint(char *path)
{
    int fd;
    char buf[BUFFER_SIZE];

    memset(buf, 0, BUFFER_SIZE);

    fd = open(path, O_RDONLY);
    if (read(fd, buf, BUFFER_SIZE) < 0) {
        errmsg("error reading file %s (%s).\n", path, strerror(errno));
        return -1;
    }
    close(fd);

    return strtol(buf, 0x00, 10);
}

static int
writeint_fd(int fd, int value)
{
    char buf[BUFFER_SIZE];
    ssize_t size;

    snprintf(buf, BUFFER_SIZE, "%d", value);
    size = (ssize_t)strlen(buf);
    return write(fd, buf, size);
}

static int
writeint(char *path, int value)
{
    int fd;

    fd = open(path, O_WRONLY);
    if (writeint_fd(fd, value) < 0) {
        errmsg("error writing file %s (%s).\n", path, strerror(errno));
        return -1;
    }
    close(fd);

    return 0;
}

int
_sysfs_init_wdt(kdogs_wdt *wdt)
{
    if (_sysfs_get_timeout(wdt) < 0) {
        errmsg("error reading timeout from %s (%s)\n", wdt->path, strerror(errno));
        return -1;
    }

    return 0;
}

int
_sysfs_close_wdt(kdogs_wdt *wdt)
{
    return 0;
}

int
_sysfs_kick(kdogs_wdt *wdt)
{
    return _sysfs_set_timeout(wdt, wdt->timeout);
}

int
_sysfs_get_timeout(kdogs_wdt *wdt)
{
    char period[PATH_SIZE];

    if (wdt->timeout > 0)
        return wdt->timeout;

    snprintf(period, PATH_SIZE, "%s/period", wdt->path);
    wdt->timeout = readint(period);

    return wdt->timeout;
}

int
_sysfs_set_timeout(kdogs_wdt *wdt, int timeout)
{
    char period[PATH_SIZE];

    snprintf(period, PATH_SIZE, "%s/period", wdt->path);

    if (writeint(period, timeout) < 0) {
        errmsg("error kicking watchdog %s/period (%s).\n", wdt->path, strerror(errno));
        return -1;
    }

    return 0;
}

int
_sysfs_get_counter(kdogs_wdt *wdt)
{
    char counter[PATH_SIZE];

    snprintf(counter, PATH_SIZE, "%s/counter", wdt->path);
    return readint(counter);
}

